﻿/**
* @class Trajectory
* 
* @author 		nada // x.nada.x@gmail.com
* @version		1.0.0
* @description		berechnet einen schiefen wurf....
* 
* @usage		Trajectory::new Trajectory(startVelocity:Number[m/s], startAngle[degrees]:Number, startHeight[m]:Number);
* @usage		Trajectory::new Trajectory(startVelocity:Number[m/s], startAngle[degrees]:Number, startHeight[m]:Number [, alternative gravity[ms-2]:Number] );
* 
* 			all in and out values are in seconds, meters or degrees.
* 			
* 			//create a movieclip with an instance called ball
* 
* 			import Trajectory;
*			
*			var t:Trajectory = new Trajectory(5, 45, 5);
*
*			trace("position at 0.6 sec: x: " + t.getTimePosition(0.6).x);
*			trace("                     y: " + t.getTimePosition(0.6).y);	
*			trace("----------------------------------------------------");
*			trace("angle at 0.6 sec: " + t.getTimeAngle(0.6));
*			trace("----------------------------------------------------");			   
*			trace("velocity at 0.6 sec: vx: " + t.getTimeVelocity(0.6).x);
*			trace("                     vy: " + t.getTimeVelocity(0.6).y);
*			trace("----------------------------------------------------");							   
*			trace("y value at 2.7 m: " + t.getY(2.7));
*			trace("----------------------------------------------------");
*			trace("trajectory width: " + t.getWidth());
*			trace("trajectory time: " + t.getTime()); 
*			trace("----------------------------------------------------");;	
*			trace("peak: x: " + t.getPeak().x); 
*			trace("      y: " + t.getPeak().y); 
*			trace("      at " + t.getPeakTime() + " seconds");
*				
*			iv = setInterval(this, "move", 20);
*			
* 			
*			function move() {
*				ball._x += 1;
*				ball._y = 600 - (t.getY(ball._x / 100) * 100);
*				if(ball._y >= 600) {
*					ball._y = 600;
*				}
*			}
*	
* 
*/

class ch.sfug.math.mechanics.Trajectory 
{
		
	private var v0:Number;
	private var theta:Number;
	private var h:Number;
	
	private var g:Number = 9.81;	//fallbeschleunigung

	/**
	 * Constructor
	 * 
	 * you can give an additional argument as alternative gravity
	 * 
	 * @param   v0		start velocity [m/s]  
	 * @param   theta 	start angle [degrees]
	 * @param   h     	start height [m]
	 *
	 * @return  Trajectory
	 */
	
	public function Trajectory (v0:Number, theta:Number, h:Number)
	{
		this.v0 = v0;
		this.theta = theta;
		this.h = h;
		
		//is there an different gravity??
		if(arguments.length == 4) {
			g = arguments[3];
			trace("g has been changed to " + g);
			trace("--------------------------------");
		}
	}
	
	/* public functions */
	/* *************************************************************************************** */
	
	/**
	 * calculates the position at a given time. 
	 * the return object contains x and y property.
	 * 
	 * @param   t	time in seconds
	 * @return  Object
	 */
	
	public function getTimePosition(t:Number):Object
	{
		var xt:Number = vx0 * t;
		var yt:Number = h + (vy0 * t) - ((g / 2) * t * t);
		
		return ({x:xt, y:yt});
	}
	
	/**
	 * calculates the velocity at a given time.
	 * the return object contains x and y property, that are equal to vx and vy.
	 * 
	 * @param   t	time in seconds
	 * @return  Object 
	 */
	
	public function getTimeVelocity(t:Number):Object
	{
		var vxt:Number = vx0;
		var vyt:Number = vy0 - (g * t);
		
		return ({x:vxt, y:vyt});
	}
	
	/**
	 * calculates the tangent angle at a given time.
	 * 
	 * @param   t	time in seconds 
	 * @return  Number
	 */
	
	public function getTimeAngle(t:Number):Number
	{
		var v:Object = getTimeVelocity(t);
		return (getDeg(Math.atan(v.y / v.x)));
	}
	
	/**
	 * calculates the y coordinate at a given x coordinate
	 * 
	 * @param   x	the x coordinate in meters
	 * @return  Number
	 */
	
	public function getY(x:Number):Number
	{
		return ( h + ((vy0 / vx0) * x) - ((g / (2 * vx0 * vx0)) * x * x) );
	}
	
	/**
	 * calculates the width at the time the trajectory hits the floor (y = 0)
	 * 
	 * @return  Number
	 */
	
	public function getWidth():Number
	{
		return ( (vx0 / g) * (vy0 + Math.sqrt((vy0 * vy0) + (2 * g * h))) );
	}
	
	/**
	 * calculates the time of the trajectory until it hits the floor (y = 0)
	 * 
	 * @return  Number
	 */
	
	public function getTime():Number 
	{
		return( (vy0 / g) + ( (1 / g) * Math.sqrt((vy0 * vy0) + (2 * g * h)) ) );
	}
	
	/**
	 * calculates the coordinates of the trajectory's peak
	 * the return object contains x and y property.
	 * 
	 * @return  Object
	 */
	
	public function getPeak():Object 
	{
		var xp:Number = vx0 * vy0 / g;
		var yp:Number = getY(xp);
		
		return ({x:xp, y:yp});
	}
	
	/**
	 * calculates the time in seconds when the peak is reached
	 * 
	 * @return  Number
	 */
	
	public function getPeakTime():Number
	{
		return(vy0 / g);
	}
	
	
	/* private functions */
	/* *************************************************************************************** */
	
	public function get vx0 ():Number
	{
		return (v0 * Math.cos(getRad(theta)));
	}
	
	public function get vy0 ():Number
	{
		return (v0 * Math.sin(getRad(theta)));
	}
	
	public function getRad(a:Number):Number 
	{
		return (a / 180 * Math.PI);
	}
	
	public function getDeg(a:Number):Number 
	{
		return (a / Math.PI * 180);
	}
	
	
}